package com.zjq.security.security;

import com.zjq.security.security.handler.MyFailHandler;
import com.zjq.security.security.handler.MySuccesHandler;
import com.zjq.security.security.service.MyUserSetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;

/**
 * @User zhangjiaqi
 * @Project security
 * @Package com.zjq.security.security
 * @Date 2022/3/28 20:54
 */

@Component
@EnableWebSecurity//开启spring security
@EnableGlobalMethodSecurity(prePostEnabled = true,jsr250Enabled = true,proxyTargetClass = true)//开启注解进行权限判断
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    private MySuccesHandler mySuccesHandler;

    private MyFailHandler myFailHandler;

    @Autowired
    public void setMyFailHandler(MyFailHandler myFailHandler) {
        this.myFailHandler = myFailHandler;
    }

    @Autowired
    public void setMySuccesHandler(MySuccesHandler mySuccesHandler) {
        this.mySuccesHandler = mySuccesHandler;
    }

    private MyUserSetailService myUserSetailService;

    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    public void setbCryptPasswordEncoder(BCryptPasswordEncoder bCryptPasswordEncoder) {
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
    }

    @Autowired
    public void setMyUserSetailService(MyUserSetailService myUserSetailService) {
        this.myUserSetailService = myUserSetailService;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserSetailService)//我们就知道了数据库中密码
                .passwordEncoder(bCryptPasswordEncoder);//密码可能是MD5,需要转换等等,我们指定一个密码的转换方式
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        //以下地址会被排除在spring security之外,大部分情况下和下面permitAll效果一样,这个就是直接不走security
        web.ignoring().antMatchers("/js/**","/css/**");//放行我们所需要放行的地址
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //告诉security,我们页面传递过滤的数据中哪个是用户,哪个是密码
        http.csrf().disable();
        http.authorizeRequests()//认证请求
                .and().formLogin()//spring security给我们提供一个默认的登录页面,默认地址就是/login,我们可以改
                //.disable()//禁用,默认的登录方式
                .loginPage("/login.html")//自定义登录页面
                .loginProcessingUrl("/login")//自定义我们的登录处理地址,注意这个地址不需要我们写controller,我们只需要写路径就行,security会自动帮我们处理这个地址,所以这个地址不要和项目的地址重复
                //.usernameParameter("uName")//自定义用户名的参数,默认是username,如果是用的默认页面,可以忽略
                //.passwordParameter("pwd");//自定义密码的参数
                .successHandler(mySuccesHandler)//自定义成功之后怎么办?//我们有两个事情要做,第一是成功之后返回什么,第二个是登录成功之后出查询用户的权限
                .failureHandler(myFailHandler)//登录失败后怎么做
                .permitAll()//放行
                .and().logout()
                .logoutUrl("/logout").permitAll()//自定义退出的地址,这个地址也不需要你写,security会自动退出并清理登录数据
                .and().authorizeRequests().anyRequest()//任意地址,除了上面单独配置的其他地址
                .authenticated();//必须登录才可以放访问,是否需要登录取决于业务

    }
}
